<template>
  <TableBody>
    <template #header>
      <TableHeader ref="tableHeaderRef" :show-filter="false" :title="fatherInfo.name">
        <template #top-right>
<!--          {{fatherInfo}}-->
          <n-tag type="error"> {{stageMenuMap.get("0")}} : {{ fatherInfo.stageIds.get("0")?fatherInfo.stageIds.get("0"):0}} </n-tag>
          <n-tag type="success"> {{stageMenuMap.get("1")}} : {{fatherInfo.stageIds.get("1")?fatherInfo.stageIds.get("1"):0}} </n-tag>
          <n-tag type="default"> {{stageMenuMap.get("3")}} : {{fatherInfo.stageIds.get("3")?fatherInfo.stageIds.get("3"):0}} </n-tag>
          <AddButton @add="onAddItem" />
        </template>
      </TableHeader>
    </template>
    <template #default>
      <n-layout
          has-sider
          style="height: 450px"
      >
        <n-layout-sider
            bordered
            show-trigger
            collapse-mode="width"
            :collapsed-width="64"
            :width="150"
            :native-scrollbar="false"
            style="max-height: 500px"
        >
          <n-menu
              v-model:value="getInfo.state"
              :collapsed-width="64"
              :collapsed-icon-size="22"
              :options="satgeMenuOptions"
          />
        </n-layout-sider>
        <n-layout-content content-style="padding: 24px;">
          <n-data-table
              :loading="table.tableLoading.value"
              :data="table.dataList.value as Array<object>"
              :row-key="rowKey"
              :columns="tableColumns"
              :scroll-x="500"
              :style="{ height: `${table.tableHeight.value*2}px` }"
              :flex-height="true"
              :row-props="rowProps"
              :pagination="false"
              :bordered="false"
              :id="'stageModeItemDragTable'+props.type"
              handle="#handle-drag"
          />
          <n-dropdown
              placement="bottom-start"
              trigger="manual"
              :x="xRef"
              :y="yRef"
              :options="options"
              :show="showDropdownRef"
              :on-clickoutside="onClickoutside"
              @select="handleSelect"
          />
        </n-layout-content>
      </n-layout>

<!--          @update:checked-row-keys="onRowCheck"-->

    </template>
  </TableBody>
  <ModalDialog ref="modalDialogRef" @confirm="onDataFormConfirm" contentHeight="120vh">
    <template #content>
      <DataForm ref="dataFormRef" :options="formItems" :form-config="formConfig"/>
    </template>
  </ModalDialog>
  <StageMoveModal v-model:model-value="stageMoveData"></StageMoveModal>
</template>
<script lang="ts">
import {TableActionModel, usePagination, useRenderAction, useRowKey, useTable, useTableColumn} from "@/hooks/table";
import {DataTableColumn, FormProps, NAvatar, NInput, NTime, SelectOption, useDialog, useMessage} from "naive-ui";
import {post, Response} from "@/api/http";
import {
  addLifeModeItems,
  addStage, changeGoalState, changeLifeModeItemsOrder, changeStageOrder, changeStageState,
  deleteStage, getFieldById,
  getFieldSelect, getFieldsTree, getGoal,
  getGoalSelect,
  getStagesList,
  getTableList
} from "@/api/url";
import {defineComponent, h, onMounted, ref, watch, defineProps, nextTick, reactive, computed} from "vue";
import {renderSelect, renderTag, renderTimePicker, renderTreeSelect,renderIcon} from "@/hooks/form";
import GoalTree from "@/views/field/goal/GoalTree.vue";
import useUserStore from "@/store/modules/user";
import UseSurfaceSettingStore from "@/store/modules/surfaceSetting";
import { DataFormType, ModalDialogType, FormItem } from '@/types/components'
import {TreeSelectOption} from "naive-ui/lib/tree-select/src/interface";
import { Book } from "@vicons/ionicons5";
import {UseConstsStore} from "@/store/modules/consts";
import pinia from "@/store/pinia";
import {obj2Map} from "@/utils";
import Sortable from "sortablejs";
import {useRouter} from "vue-router";
import MyTime from "@/views/task/time/MyTime.vue";
import StageMoveModal from "@/views/field/stage/StageMoveModal.vue";

interface FieldData {
  id?:number
  name?:string
  stageIds?:Map<number,Array<number>>
  label?:string
  key?:number
  fatherId?:number
  children?:Array<GoalData>
  hasOnStage?:boolean
}
interface GoalData {
  id?:number
  goalName?:string
  goalDesc?:string
  state?:number
  lastStartTime?:number
  timePeriods?:Array<number>
  goalScore?:number
  goalConclusion?:string
  stageIds?:Map<number,Array<number>>
}
interface StageData{
  id:number
  name:string
  state:number
  lastStartTime:number
  timePeriods:Array<number>
  fieldId:number
  goalId:number
  finished:boolean
  tasks:Map<number,Map<number,Array<number>>>
  // finishTasks
}

export default defineComponent({
  name: 'StageTable',
  components: {StageMoveModal},
  props:{
    type:Number
  },
  setup(props) {
    const key = ref(new Date().getTime())
    const table = useTable()
    const rowKey = useRowKey('id')
    const naiveDialog = useDialog()
    const message = useMessage()
    const userStore = useUserStore()
    const useSurfaceSetting = UseSurfaceSettingStore()
    const useConsts = UseConstsStore()
    const router = useRouter()

    // const pagination = usePagination(doRefresh)
    const checkedRowKeys = [] as Array<any>
    const surfaceSetting = useSurfaceSetting.getSurfaceSetting();
    const satgeMenuOptions = computed(()=>{
      return useConsts.getStateList().map(u=>{return {...u,icon:renderIcon(Book)}})
    })
    const stageMenuMap = computed(()=>{
      return obj2Map(useConsts.getConsts().stateMap)
    })
    const tableColumns = useTableColumn(
        [
          table.selectionColumn,
          // table.indexColumn,
          {
            title: 'id',
            key: 'id',
          },
          {
            title: '阶段名',
            key: 'name',
          },
          {
            title: '上次开启时间',
            key: 'lastStartTime',
            render: (rowData) => {
              return h(MyTime,{
                time:rowData.lastStartTime,
                type:"datetime"
              },{})
            }
          },
          {
            title: '操作',
            key: 'actions',
            render: (rowData) => {
              let type = 'default'
              if(rowData.id === useSurfaceSetting.getSurfaceSetting().onLifeModeId)
                type = 'error';
              return useRenderAction([
                {
                  label: '上下移动',
                  type:type,
                  // onClick: onUpdateItem.bind(null, rowData),
                  id: "handle-drag"
                }
              ] as TableActionModel[])
            },
          },
        ],
        {
          align: 'center',
        } as DataTableColumn
    )
    const getInfo = reactive({
      id:(props.type === 0?surfaceSetting.showGoalId:surfaceSetting.showFieldId)[0],
      state: JSON.stringify( props.type === 0?surfaceSetting.showGoalState:surfaceSetting.showFieldState)
    })

    const fatherInfo = ref({name:'无',stageIds:new Map()})
    const getFatherInfo = async ()=>{
      if(props.type === 1){
        try {
          // table.tableLoading.value = true;
          const data: Response = await post({
            url: getFieldById,
            data:{id:getInfo.id},
            token:userStore.getToken()
          });
          const d = data.data.data as FieldData
          if(d && d.name){
            const map = new Map()
            if(d.stageIds && Object.keys(d.stageIds).length > 0){
              const time = obj2Map(d.stageIds);
              for (const timeKey of time.keys()) {
                map.set(timeKey,time.get(timeKey).length)
              }
            }
            fatherInfo.value =  {name:d.name, stageIds:map}
          }else fatherInfo.value =  {name:'', stageIds:new Map()}
        }catch(e) {
          message.error((e as Error).message)
        }finally {
          // table.tableLoading.value = false;
        }
      }
      if(props.type ===0){
        try {
          // table.tableLoading.value = true;
          const data: Response = await post({
            url: getGoal,
            data:{id:getInfo.id},
            token:userStore.getToken()
          });
          const d = data.data.data as GoalData
          if(d && d.goalName){
            const map = new Map()
            if(d.stageIds && Object.keys(d.stageIds).length > 0){
              const time = obj2Map(d.stageIds);
              for (const timeKey of time.keys()) {
                map.set(timeKey,time.get(timeKey).length)
              }
            }
            fatherInfo.value =  {name:d.goalName, stageIds:map}
          }else fatherInfo.value =  {name:'', stageIds:new Map()}
        }catch(e) {
          message.error((e as Error).message)
        }finally {
          // table.tableLoading.value = false;
        }
      }
    }

    watch(getInfo,()=>{
      const setting = useSurfaceSetting.getSurfaceSetting()
      if(props.type === 0){
        setting.showGoalState = parseInt(getInfo.state)
      }else {
        setting.showFieldState = parseInt(getInfo.state)
      }
      // console.log(setting)
      doRefresh()
    })
    watch(useSurfaceSetting.getSurfaceSetting(),()=>{
      const setting = useSurfaceSetting.getSurfaceSetting()
      if(( props.type === 0 && getInfo.id !== setting.showGoalId[0])
      || (props.type === 1 && getInfo.id !== setting.showFieldId[0])){
        getInfo.id = (props.type === 0?surfaceSetting.showGoalId:surfaceSetting.showFieldId)[0]
        key.value = new Date().getTime()
      }
    })

    const stageMoveData = reactive({
      id:0,
      toMove: false,
      stageId: 0,
      fieldId:0,
      goalId:0,
      oldFieldId:0,
      oldGoalId:0,
      state:0})
    watch(stageMoveData,()=>{
      if(!stageMoveData.toMove) doRefresh()
    })
    // 加载数据
    async function doRefresh() {
      const info = getInfo
      post({
        url: getStagesList,
        data: {id:info.id,type:props.type,state:info.state},
        token:userStore.getToken()
      }).then(async (res: Response) => {
        // console.log(res.data.data)
        await table.handleSuccess({data:res.data.data})
        // console.log(table.dataList)
        getFatherInfo()
        setSort()
      }).catch(console.log)
      await getGoalAndFieldSelect()
    }
    onMounted(doRefresh)
    watch(table.tableLoading,()=>{
      if(!table.tableLoading.value){
        doRefresh()
      }
    })

    // 添加/编辑框
    const goalSelect:Array<any> = [];
    const fieldSelect:Array<any> = [];
    const getGoalAndFieldSelect = async ()=>{
      try {
        const data: Response = await post({
          url: getGoalSelect,
          data: {haveFinish:false},
          token:userStore.getToken()
        });
        // console.log(data)
        goalSelect.splice(0);
        goalSelect.push(...data.data.data)
        // console.log(goalSelect)
      }catch(e) {
        message.error((e as Error).message)
      }finally {
      }
      try {
        const data: Response = await post({
          url: getFieldSelect,
          token:userStore.getToken()
        });
        // console.log(data)
        fieldSelect.splice(0);
        fieldSelect.push(...data.data.data)
        // console.log(fieldSelect)
      }catch(e) {
        message.error((e as Error).message)
      }finally {
      }
    }
    const formConfig = {
      labelWidth: 100,
      size: 'medium',
      labelAlign: 'right',
    } as FormProps
    const formItems = [
      {
        label: 'id',
        type: 'input',
        key: 'id',
        hidden:true,
        disabled:true,
        value: ref(null),
        render: (formItem) => {
          return h(NInput, {
            hidden:true,
            disabled:true,
            value: formItem.value.value,
            onUpdateValue: (val) => {
              formItem.value.value = val
            },
          })
        },
      },
      {
        label: '名称',
        type: 'input',
        key: 'name',
        value: ref(null),
        validator: (formItem, message) => {
          if (!formItem.value.value) {
            message.error('请输入角色名称')
            return false
          }
          return true
        },
        render: (formItem) => {
          return h(NInput, {
            value: formItem.value.value,
            onUpdateValue: (val) => {
              formItem.value.value = val
            },
            placeholder: '请输入角色名称',
          })
        },
      },
      {
        label: '状态',
        key: 'state',
        hidden:true,
        value: ref(getInfo.state),
        optionItems: useConsts.getStateList().map(u=>{return{
          label:u.label, value:u.key
        }}),
        reset:(formItem)=>{
          formItem.value.value = getInfo.state
        },
        render: (formItem) =>
            renderSelect(formItem.value, formItem.optionItems as SelectOption[], {
              placeholder: '请选择会议类型',
              clearable: true,
              disabled:true,
            }),
      },
      {
        label: '领域',
        key: 'fieldId',
        value: ref(useSurfaceSetting.getSurfaceSetting().showFieldId[0]),
        optionItems:fieldSelect,
        reset:(formItem)=>{
          formItem.value.value = useSurfaceSetting.getSurfaceSetting().showFieldId[0]
        },
        render: (formItem) =>
            renderTreeSelect(formItem.value, formItem.optionItems as TreeSelectOption[], {
              placeholder: '请选择会议类型',
              clearable: true,
              filterable:true
            }),
      },
      {
        label: '目标',
        key: 'goalId',
        value: ref(useSurfaceSetting.getSurfaceSetting().showGoalId[0]),
        optionItems: goalSelect,
        reset:(formItem)=>{
          formItem.value.value = useSurfaceSetting.getSurfaceSetting().showGoalId[0]
          console.log(formItem.value.value)
        },
        render: (formItem) =>
            renderSelect(formItem.value, formItem.optionItems as SelectOption[], {
              placeholder: '请选择会议类型',
              clearable: true,
              filterable:true
            }),
      },
      {
        label: '描述',
        key: 'desc',
        value: ref(null),
        maxLength: 200,
        inputType: 'text',
        validator: (formItem, message) => {
          if (!formItem.value.value) {
            message.error('请输入角色名称')
            return false
          }
          return true
        },
        render: (formItem) => {
          return h(NInput, {
            value: formItem.value.value,
            onUpdateValue: (val) => {
              formItem.value.value = val
            },
            placeholder: '请输入角色描述',
            type: 'textarea',
            rows: 5,
          })
        },
      },
    ] as FormItem[]
    let toAdd = 0;
    const modalDialogRef = ref<ModalDialogType | null>(null)
    const dataFormRef = ref<DataFormType | null>(null)
    async function onDataFormConfirm() {
      if (dataFormRef.value?.validator()) {
        modalDialogRef.value?.toggle()
        const params = {...dataFormRef.value.generatorParams(), toAdd:toAdd}
        if(toAdd === 1 && params.state) params.state = parseInt(getInfo.state);
        await addItem(params)
      }
    }

    // 删除添加
    function onAddItem() {
      toAdd = 0;
      modalDialogRef.value?.toggle()
      nextTick(() => {
        dataFormRef.value?.reset()
        console.log(dataFormRef.value)
      })

    }
    function onUpdateItem(item: any) {
      // console.log(item)
      toAdd = 1;
      modalDialogRef.value?.toggle()
      nextTick(() => {
        formItems.forEach((it) => {
          const key = it.key
          const propName = item[key]
          // console.log(item[key])
          if (propName) {
            it.value.value = propName
            if(key == "state") it.value.value = JSON.stringify(propName)
          }
        })
      })
    }
    function onDeleteItem(item: any) {
      naiveDialog.warning({
        title: '提示',
        content: '确定要删除此数据吗？',
        positiveText: '确定',
        onPositiveClick: async () => {
          table.dataList.value!.splice(table.dataList.value!.indexOf(item), 1)
          try {
            // table.tableLoading.value = true;
            const data: Response = await post({
              url: deleteStage,
              data: item,
              token:userStore.getToken()
            });
            // console.log(data)
            message.success(data.msg)
          }catch(e) {
            message.error((e as Error).message)
          }finally {
            // table.tableLoading.value = false;
          }
        },
      })
    }
    const addItem = async (params:any)=>{
      try {
        table.tableLoading.value = true;
        const data: Response = await post({
          url: addStage,
          data: params,
          token:userStore.getToken()
        });
        // console.log(data)
        message.success(data.msg)
      }catch(e) {
        message.error((e as Error).message)
      }finally {
        table.tableLoading.value = false;
      }
    }

    // 下来菜单
    let chooseRow:StageData|null = null;
    const options = [
      {
        label: "编辑",
        key: "edit",
      },
      {
        label: "查看任务",
        key: "show",
      },
      {
        label: "开启阶段",
        key: "start",
      },
      {
        label: "暂停阶段",
        key: "stop",
      },
      {
        label: "结束阶段",
        key: "finish",
      },
      {
        label: "移动",
        key: "move",
      },
      {
        label: () => h("span", { style: { color: "red" } }, "删除"),
        key: "delete",
      },
    ];
    const showDropdownRef = ref(false);
    const xRef = ref(0);
    const yRef = ref(0);
    const onClickoutside = () => {
      showDropdownRef.value = false;
    };
    function onFinishGoal(params: StageData|null, str:string, newState:number){
      if(params){
        const func = async (id:number|undefined,beginTime:number, endTime:number|null,
                            oldState:number|undefined,newState:number) => {
          table.tableLoading.value = true;
          try {
            const data : Response = await post({
              url: changeStageState,
              data: {stageId:id,startTime:beginTime,endTime:endTime,oldState:oldState,newState:newState,fieldId:params.fieldId,goalId:params.goalId},
              token:userStore.getToken()
            });
            // console.log(data)
            message.success(data.msg)
          }catch(e) {
            message.error((e as Error).message)
          }finally {
            key.value = new Date().getTime()
            table.tableLoading.value = false;
          }
        }
        naiveDialog.warning({
          title: '提示',
          content: '是否要选择'+str+'该阶段:'+params.name+'？',
          positiveText: '记录上一段的时间',
          negativeText: '取消上一段的时间',
          onNegativeClick:()=>{
            func(params.id,new Date().getTime(),null,params.state,newState)
          },
          onPositiveClick:() => {
            func(params.id,new Date().getTime(),new Date().getTime(),params.state,newState)
          },
        })
      }
    }
    const handleSelect = (key: string, node: string) => {
      // console.log(key, node);
      showDropdownRef.value = false;
      if (key == "edit") {
        onUpdateItem(chooseRow)
      }
      if (key == "delete") {
        onDeleteItem(chooseRow)
      }
      const str = key==='start'?'开启':key==='stop'?'暂停':'结束';
      if(key == "show"){
        if(chooseRow?.id)
          useSurfaceSetting.addIdToArray(chooseRow.id,useSurfaceSetting.getSurfaceSetting().showStageId)
        router.replace({
          path: '/task/TaskPanel', // route.query.redirect ? (route.query.redirect as string) : '/',
        })
      }
      if (key == "start") {
        onFinishGoal(chooseRow,str,0)
      }
      if (key == "stop") {
        onFinishGoal(chooseRow,str,1)
      }
      if (key == "finish") {
        onFinishGoal(chooseRow,str,3)
      }
      if (key == "move") {
        // onFinishGoal(chooseRow,str,3)
        stageMoveData.id = <number>chooseRow?.id
        stageMoveData.fieldId = <number>chooseRow?.fieldId
        stageMoveData.oldFieldId = <number>chooseRow?.fieldId
        stageMoveData.goalId = <number>chooseRow?.goalId
        stageMoveData.oldGoalId = <number>chooseRow?.goalId
        stageMoveData.state = <number>chooseRow?.state
        stageMoveData.toMove = true
      }
    };

    const rowProps = (row:StageData) => {
      return {
        // 双击
        ondblclick: (e: MouseEvent) => {
          e.preventDefault()
          // message.info(JSON.stringify(row, null, 2));
          showDropdownRef.value = true;
          xRef.value = e.clientX;
          yRef.value = e.clientY;
          // console.log('rowProps',row)
          chooseRow = row
        },
        onContextmenu: (e: MouseEvent) => {
          e.preventDefault()
          // message.info(JSON.stringify(row, null, 2));
          showDropdownRef.value = true;
          xRef.value = e.clientX;
          yRef.value = e.clientY;
          // console.log('rowProps',row)
          chooseRow = row
        },
      };
    };

    // 移动
    function setSort() {
      /* 阻止火狐浏览器在  vue-draggable组件时拖动 打开新窗口 */
      document.body.ondrop = function(event) {
        event.preventDefault();
        event.stopPropagation();
      };

      let el = document.querySelector("#stageModeItemDragTable"+props.type+" table tbody");
      // console.log('el',el);
      if(el)
        new Sortable(el as any, {
          handle: "#handle-drag",
          sort: true,
          ghostClass: "sortable-ghost",
          preventOnFilter: false,
          onEnd: async function (/**Event*/ e: any) {
            const list = table.dataList.value?.map(l=>l.id);
            if(list){
              const targetRow = list.splice(e.oldIndex, 1)[0];
              list.splice(e.newIndex, 0, targetRow);
              // console.log(list)
              try {
                const setting = useSurfaceSetting.getSurfaceSetting()
                table.tableLoading.value = true;
                const data : Response = await post({
                  url: changeStageOrder,
                  data: props.type===0?{ids:list,goalId:setting.showGoalId[0],state:getInfo.state}:{ids:list,state:getInfo.state,fieldId:setting.showFieldId[0]},
                  token:userStore.getToken()
                });
                // console.log(data)
                message.success(data.msg)
              }catch(e) {
                message.error((e as Error).message)
              }finally {
                table.tableLoading.value = false;
              }
            }
            // console.log(e)
            // e.preventDefault()
          },
        });
    }


    function onRowCheck(rowKeys: Array<any>) {
      checkedRowKeys.length = 0
      checkedRowKeys.push(...rowKeys)
    }
    return {
      xRef,yRef,options,handleSelect,onClickoutside,showDropdownRef,fatherInfo,stageMenuMap,stageMoveData,
      getInfo,satgeMenuOptions,
      modalDialogRef,dataFormRef,onDataFormConfirm,
      rowProps,formConfig,formItems,
      props,onAddItem,
      table,
      rowKey,checkedRowKeys,onDeleteItem,
      onRowCheck,tableColumns,
      pattern: ref(''),
    }
  },
})

</script>

<style lang="scss" scoped>
.avatar-container {
  position: relative;
  width: 30px;
  margin: 0 auto;
  vertical-align: middle;
  .avatar {
    width: 100%;
    border-radius: 50%;
  }
  .avatar-vip {
    border: 2px solid #cece1e;
  }
  .vip {
    position: absolute;
    top: 0;
    right: -9px;
    width: 15px;
    transform: rotate(60deg);
  }
}
.gender-container {
  .gender-icon {
    width: 20px;
  }
}
</style>